pub fn main() {
    owner_ship_demo();
    struct_clone();
}

fn owner_ship_demo() {
    // 字符串字面量
    let a = "1"; // 是字符串字面量,指向的是创建时的只读空间
    let b = a;
    println!("{},{}",a,b);

    // 字符串对象,所有权转移
    let c = "1".to_string(); // 保存的是String对象,该对象结构是[堆空间的指针,空间大小,字符串长度]
    let _d = c;
    // print!("{},{}",c,_d); // 此处c被移动无法读取,编译即报错

    //reference 引用  & 也称为借用,并不会获得所有权,所以不会再使用完后销毁,也可以用在形参中
    let e = "e".to_string();
    let f = &e; 
    println!("e:{},f:{}",e,f);


    // 可变引用,暂时跳过,有点迷糊,大概理解类似于读写分离,可以有多个读缓存,但只能从一处写入

    // 在同一作用域下,对某一块数据:
    // 1.可以有多个不可变引用
    // 2.只能有一个可变的引用
    // 3.不能同时拥有一个可变引用和一个不可变引用
}

// #[derive(Clone)]
#[derive(Clone,Copy)]
struct A<'a> {
    a:i32,
    // name:String // Copy必须用在长度固定的类型上
    name:&'a str // 由于无法推断出生命周期，会缺少生命期说明符，需要命名生命期参数
}

fn struct_clone() {
    let x:A = A{a:1,name:"name"};
    let y:A = x;
    // println!("{}",x.a); // 此处x被销毁,无法使用,编译报错

    let mut z:A = y.clone();
    println!("{}",z.a); // 此时可以使用

    use_struct(&y);
    use_struct(&x); // 如果没有copy特质则报错
    use_struct2(&mut z);
    
}

fn use_struct(a:&A) { // A的引用
    println!("A的引用:{}",a.a);
    let b = a;
    let c = a;
    println!("同一作用域下可以有多个不可变引用{},{}",b.a,c.a);
}

fn use_struct2(a:&mut A) { // A的可变引用
    a.a = 2;
    println!("A的可变引用:{},{}",a.a,a.name);
    let _aa = a;
    // let _ab = a; //不可以有多个可变引用，此处报错


    let mut s = "123".to_string();

    let ss = &mut s;
    // let s1 = &mut s;

    // 上面的代码没有改变属性值，不会报错
    ss.push_str("string"); // 如果打开该行代码编译器会报错,只能有一个可变引用
    // println!("只能有一个可变引用:{}{}",ss,s1); // 如果打开该行代码编译器会报错,只能有一个可变引用


    // 3.可以同时存在一个可变引用，和多个不可变引用
    let ns = &s;
    let ns2 = &s;

    println!("3.可以同时存在一个可变引用，和多个不可变引用:{},{},{}",ns,ns2,s);
} 